/******************************************************************************* * Copyright (c) MOBAC developers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package mobac.gui.atlastree; import java.awt.HeadlessException; import java.awt.Point; import java.awt.datatransfer.Transferable; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragGestureRecognizer; import java.awt.dnd.DragSource; import java.awt.dnd.DragSourceDragEvent; import java.awt.dnd.DragSourceDropEvent; import java.awt.dnd.DragSourceEvent; import java.awt.dnd.DragSourceListener; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetContext; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import javax.swing.JOptionPane; import javax.swing.JTree; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import mobac.exceptions.InvalidNameException; import mobac.program.interfaces.LayerInterface; import mobac.program.interfaces.MapInterface; import mobac.program.model.AtlasTreeModel; import mobac.utilities.I18nUtils; import org.apache.log4j.Logger; public class DragDropController { static Logger log = Logger.getLogger(DragDropController.class); public DragDropController(JAtlasTree atlasTree) { super(); this.atlasTree = atlasTree; new AtlasDragSource(); new AtlasDropTarget(); } JAtlasTree atlasTree; protected class AtlasDragSource implements DragSourceListener, DragGestureListener { final DragGestureRecognizer recognizer; final DragSource source; public AtlasDragSource() { source = new DragSource(); recognizer = source.createDefaultDragGestureRecognizer(atlasTree, DnDConstants.ACTION_MOVE, this); } public void dragGestureRecognized(DragGestureEvent dge) { TreePath path = atlasTree.getSelectionPath(); if ((path == null) || (path.getPathCount() <= 1)) // We can't move the root node or an empty selection return; TreeNode oldNode = (TreeNode) path.getLastPathComponent(); if (!(oldNode instanceof LayerInterface || oldNode instanceof MapInterface)) return; Transferable transferable = new NodeTransferWrapper(oldNode); source.startDrag(dge, DragSource.DefaultMoveNoDrop, transferable, this); } /** * Called whenever the drop target changes and it has bee accepted ( */ public void dragEnter(DragSourceDragEvent dsde) { dsde.getDragSourceContext().setCursor(DragSource.DefaultMoveDrop); } public void dragOver(DragSourceDragEvent dsde) { } public void dragDropEnd(DragSourceDropEvent dsde) { } public void dragExit(DragSourceEvent dse) { dse.getDragSourceContext().setCursor(DragSource.DefaultMoveNoDrop); } public void dropActionChanged(DragSourceDragEvent dsde) { } } protected class AtlasDropTarget implements DropTargetListener { final DropTarget target; public AtlasDropTarget() throws HeadlessException { super(); target = new DropTarget(atlasTree, this); } public synchronized void dragEnter(DropTargetDragEvent dtde) { } public synchronized void dragExit(DropTargetEvent dte) { } public synchronized void dragOver(DropTargetDragEvent dtde) { try { Transferable t = dtde.getTransferable(); Object o = t.getTransferData(NodeTransferWrapper.ATLAS_OBJECT_FLAVOR); TreeNode node = getNodeForEvent(dtde); if (o instanceof LayerInterface && node instanceof LayerInterface) { dtde.acceptDrag(dtde.getDropAction()); return; } if (o instanceof MapInterface && node instanceof LayerInterface || node instanceof MapInterface) { dtde.acceptDrag(dtde.getDropAction()); return; } dtde.rejectDrag(); } catch (Exception e) { log.error("", e); } } public void dropActionChanged(DropTargetDragEvent dtde) { } public synchronized void drop(DropTargetDropEvent dtde) { try { TreeNode sourceNode = (TreeNode) dtde.getTransferable().getTransferData( NodeTransferWrapper.ATLAS_OBJECT_FLAVOR); Point pt = dtde.getLocation(); DropTargetContext dtc = dtde.getDropTargetContext(); JTree tree = (JTree) dtc.getComponent(); TreePath parentpath = tree.getClosestPathForLocation(pt.x, pt.y); TreeNode targetNode = (TreeNode) parentpath.getLastPathComponent(); if (targetNode.equals(sourceNode) || targetNode.getParent().equals(sourceNode)) { dtde.rejectDrop(); return; } AtlasTreeModel atlasTreeModel = (AtlasTreeModel) atlasTree.getModel(); if (sourceNode instanceof LayerInterface && targetNode instanceof LayerInterface) mergeLayers(atlasTreeModel, (LayerInterface) sourceNode, (LayerInterface) targetNode); if (targetNode instanceof MapInterface) // We can not make a map child of another map // -> use it's layer instead targetNode = targetNode.getParent(); if (sourceNode instanceof MapInterface && targetNode instanceof LayerInterface) moveMap(atlasTreeModel, (MapInterface) sourceNode, (LayerInterface) targetNode); } catch (Exception e) { log.error("", e); atlasTree.getTreeModel().notifyStructureChanged(); dtde.rejectDrop(); } } protected void mergeLayers(AtlasTreeModel atlasTreeModel, LayerInterface sourceLayer, LayerInterface targetLayer) throws InvalidNameException { int answer = JOptionPane.showConfirmDialog(null, String.format(I18nUtils.localizedStringForKey("msg_confirm_merge_layer"), sourceLayer.getName(), targetLayer.getName()), I18nUtils.localizedStringForKey("msg_confirm_merge_layer_title"), JOptionPane.YES_NO_OPTION); if (answer != JOptionPane.YES_OPTION) return; try { atlasTreeModel.mergeLayers(sourceLayer, targetLayer); } catch (InvalidNameException e) { JOptionPane.showMessageDialog(null, e.getMessage(), I18nUtils.localizedStringForKey("msg_merge_layer_failed"), JOptionPane.ERROR_MESSAGE); throw e; } } protected void moveMap(AtlasTreeModel atlasTreeModel, MapInterface map, LayerInterface targetLayer) throws InvalidNameException { atlasTreeModel.moveMap(map, targetLayer); } private TreeNode getNodeForEvent(DropTargetDragEvent dtde) { Point p = dtde.getLocation(); DropTargetContext dtc = dtde.getDropTargetContext(); JTree tree = (JTree) dtc.getComponent(); TreePath path = tree.getClosestPathForLocation(p.x, p.y); return (TreeNode) path.getLastPathComponent(); } } }